﻿// This source file is part of WallpaperControl, a tool for automatic changing 
// of the desktop wallpaper.
// 
// Visit http://wpcontrol.sourceforge.net/ for more.
//
// Copyright (c) 2014 nscrolldev
//
// Licensed under the GPLv2.
// See http://www.gnu.org/licenses/gpl-2.0.html for details.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.


using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Diagnostics;
using System.IO;

namespace WallpaperControl
{
    /// <summary>
    /// The ControlPanel form.
    /// </summary>
    public partial class ControlPanel : Form
    {
        System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ControlPanel));

        /// <summary>
        /// True if the next wallpaper should be displayed in schedule.
        /// </summary>
        private bool _displayNextWallpaper;

        /// <summary>
        /// True if the current wallpaper should be displayed in schedule.
        /// </summary>
        private bool _displayCurrentWallpaper;

        /// <summary>
        /// Gets or sets whether the next wallpaper should be displayed in schedule.
        /// </summary>
        internal bool DisplayNextWallpaper
        {
            get
            {
                return this._displayNextWallpaper;
            }
            set
            {
                this._displayNextWallpaper = value;
            }
        }

        /// <summary>
        /// Gets or sets whether the current wallpaper should be displayed in schedule.
        /// </summary>
        internal bool DisplayCurrentWallpaper
        {
            get
            {
                return this._displayCurrentWallpaper;
            }
            set
            {
                this._displayCurrentWallpaper = value;
            }
        }

        internal ComboBox DropDownStyle
        {
            get
            {
                return this.dropdownStyle;
            }
            set
            {
                this.dropdownStyle = value;
            }
        }

        internal ListBox ListBoxImages
        {
            get
            {
                return this.listBoxImages;
            }
            set
            {
                this.listBoxImages = value;
            }
        }

        public ControlPanel()
        {
            this.InitializeComponent();
            this.InitNameStack();
            this.labelVersion.Text = string.Format(Program.Lang.GetString("Version_Number_Formatted"), Program.Version);
        }

        private void InitNameStack()
        {
            // Initialize style name list
            this.StyleNames = new List<string>();

            this.StyleNames.Insert(0, Program.Lang.GetString("Zoom_CenteredText"));
            this.StyleNames.Insert(0, Program.Lang.GetString("Zoom_TiledText"));
            this.StyleNames.Insert(0, Program.Lang.GetString("Zoom_StretchedText"));
            this.styleBindingSource.DataSource = this.StyleNames;

            // Initialize time interval name list
            this.TimeIntervalNames = new List<string>();
            this.TimeIntervalNames.Add(Program.Lang.GetString("Interval_30sec"));
            this.TimeIntervalNames.Add(Program.Lang.GetString("Interval_1min"));
            this.TimeIntervalNames.Add(Program.Lang.GetString("Interval_3min"));
            this.TimeIntervalNames.Add(Program.Lang.GetString("Interval_5min"));
            this.TimeIntervalNames.Add(Program.Lang.GetString("Interval_10min"));
            this.TimeIntervalNames.Add(Program.Lang.GetString("Interval_15min"));
            this.TimeIntervalNames.Add(Program.Lang.GetString("Interval_30min"));
            this.TimeIntervalNames.Add(Program.Lang.GetString("Interval_45min"));
            this.TimeIntervalNames.Add(Program.Lang.GetString("Interval_1h"));
            this.TimeIntervalNames.Add(Program.Lang.GetString("Interval_2h"));
            this.TimeIntervalNames.Add(Program.Lang.GetString("Interval_3h"));
            this.TimeIntervalNames.Add(Program.Lang.GetString("Interval_4h"));
            this.TimeIntervalNames.Add(Program.Lang.GetString("Interval_5h"));
            this.TimeIntervalNames.Add(Program.Lang.GetString("Interval_6h"));
            this.TimeIntervalNames.Add(Program.Lang.GetString("Interval_7h"));
            this.TimeIntervalNames.Add(Program.Lang.GetString("Interval_8h"));
            this.TimeIntervalNames.Add(Program.Lang.GetString("Interval_9h"));
            this.TimeIntervalNames.Add(Program.Lang.GetString("Interval_10h"));
            this.TimeIntervalNames.Add(Program.Lang.GetString("Interval_11h"));
            this.TimeIntervalNames.Add(Program.Lang.GetString("Interval_12h"));
            this.TimeIntervalNames.Add(Program.Lang.GetString("Interval_5sec"));
            this.timeIntervalsBindingSource.DataSource = this.TimeIntervalNames;

            // Initialize day interval name list
            this.DayIntervalNames = new List<string>();
            this.DayIntervalNames.Add(Program.Lang.GetString("Interval_1d"));
            this.DayIntervalNames.Add(Program.Lang.GetString("Interval_2d"));
            this.DayIntervalNames.Add(Program.Lang.GetString("Interval_3d"));
            this.DayIntervalNames.Add(Program.Lang.GetString("Interval_4d"));
            this.DayIntervalNames.Add(Program.Lang.GetString("Interval_5d"));
            this.DayIntervalNames.Add(Program.Lang.GetString("Interval_6d"));
            this.DayIntervalNames.Add(Program.Lang.GetString("Interval_weekly"));
            this.DayIntervalNames.Add(Program.Lang.GetString("Interval_2weeks"));
            this.DayIntervalNames.Add(Program.Lang.GetString("Interval_3weeks"));
            this.DayIntervalNames.Add(Program.Lang.GetString("Interval_monthly"));
            this.DayIntervalNames.Add(Program.Lang.GetString("Interval_2months"));
            this.DayIntervalNames.Add(Program.Lang.GetString("Interval_3months"));
            this.DayIntervalNames.Add(Program.Lang.GetString("Interval_4months"));
            this.DayIntervalNames.Add(Program.Lang.GetString("Interval_5months"));
            this.DayIntervalNames.Add(Program.Lang.GetString("Interval_6months"));
            this.dayIntervalsBindingSource.DataSource = this.DayIntervalNames;
        }

        private void buttonAdd_Click(object sender, EventArgs e)
        {
            // Add a new image
            ImageList.Instance.AddImage();
            // Keep buttons up-to-date
            this.UpdateImageButtons();
        }

        private void buttonDelete_Click(object sender, EventArgs e)
        {
            // Remove selected image
            ImageList.Instance.RemoveImage();
            // Keep buttons up-to-date
            this.UpdateImageButtons();
        }

        private void listBoxImages_SelectedIndexChanged(object sender, EventArgs e)
        {
            // Update button status
            this.UpdateImageButtons();
            // Load the selected style for selected image
            // Get index of selected image
            int selectedImage = Program.ControlPanel.ListBoxImages.SelectedIndex;
            // Make sure an image is selected
            if (selectedImage != -1)
            {
                // Check which style is selected for the image
                if (ImageList.Instance.Images[selectedImage].ZoomStyle == Wallpaper.Style.Stretched)
                {
                    this.DropDownStyle.SelectedIndex = 0;
                }
                else if (ImageList.Instance.Images[selectedImage].ZoomStyle == Wallpaper.Style.Tiled)
                {
                    this.DropDownStyle.SelectedIndex = 1;
                }
                else if (ImageList.Instance.Images[selectedImage].ZoomStyle == Wallpaper.Style.Centered)
                {
                    this.DropDownStyle.SelectedIndex = 2;
                }
            }
        }

        private void buttonUp_Click(object sender, EventArgs e)
        {
            // Move selected image up
            ImageList.Instance.MoveImageUp();
        }

        private void buttonDown_Click(object sender, EventArgs e)
        {
            // Move selected image down
            ImageList.Instance.MoveImageDown();
        }

        private void buttonPreview_Click(object sender, EventArgs e)
        {
            // Open preview
            ImageList.Instance.PreviewImage();
        }

        private void buttonOK_Click(object sender, EventArgs e)
        {
            // Save start mode
            Program.StartManager.StoreStartMode();
            // Save configuration 
            Program.CfgFileManager.SaveImageListFile();
            Program.CfgFileManager.SaveConditionFile();
            Program.CfgFileManager.SaveSettingsFile();
            Program.CfgFileManager.SaveSessionFile();
            // Close ControlPanel
            this.Close();
        }

        private void buttonCancel_Click(object sender, EventArgs e)
        {
            // Close ControlPanel - don't save settings
            this.Close();
            Program.Configuration.Restore();
        }

        private void buttonShowNow_Click(object sender, EventArgs e)
        {
            // Set selected image as wallpaper now
            //WallpaperManager.Instance.SetSelectedWallpaper();
            int index = this.listBoxImages.SelectedIndex;
            string path = ImageList.Instance.Images[index].Path;
            Wallpaper.Style style = ImageList.Instance.Images[index].ZoomStyle;
            WallpaperManager.Instance.SetWallpaper(path, style);
        }

        private void radioButtonTime_CheckedChanged(object sender, EventArgs e)
        {
            if (radioButtonTime.Checked)
            {
                // Change condition type
                Program.CurrentSession.ActiveCondition = new CondTime(this.timePicker.Value);
                // Disable controls for interval
                this.radioButtonInterval.Checked = false;
                this.comboBoxInterval.Enabled = false;
                this.radioButtonStartup.Checked = false;
                this.radioButtonDay.Checked = false;
                // Enable timepicker for time condition
                this.timePicker.Enabled = true;
            }
        }

        private void radioButtonInterval_CheckedChanged(object sender, EventArgs e)
        {
            if (radioButtonInterval.Checked)
            {
                // Change condition type
                Program.CurrentSession.ActiveCondition = new CondTimeInterval(CondTimeInterval.IntervalSeconds[this.comboBoxInterval.SelectedIndex]);
                // Disable control for time condition
                this.radioButtonTime.Checked = false;
                this.radioButtonDay.Checked = false;
                this.radioButtonStartup.Checked = false;

                this.timePicker.Enabled = false;
                this.comboBoxDay.Enabled = false;
                // Enable dropdown for interval
                this.comboBoxInterval.Enabled = true;
            }
        }

        private void radioButtonStartup_CheckedChanged(object sender, EventArgs e)
        {
            if (this.radioButtonStartup.Checked)
            {
                // Change condition type
                Program.CurrentSession.ActiveCondition = new CondStartup(0);
                // Disable settings for other condition types
                this.radioButtonTime.Checked = false;
                this.radioButtonDay.Checked = false;
                this.radioButtonInterval.Checked = false;

                this.timePicker.Enabled = false;
                this.comboBoxDay.Enabled = false;
                this.comboBoxInterval.Enabled = false;
            }
        }

        private void radioButtonDay_CheckedChanged(object sender, EventArgs e)
        {
            if (this.radioButtonDay.Checked)
            {
                // Change condition type
                Program.CurrentSession.ActiveCondition = new CondDayInterval(CondDayInterval.Days[this.comboBoxDay.SelectedIndex]);
                // Disable settings for other condition types
                this.radioButtonTime.Checked = false;
                this.radioButtonInterval.Checked = false;
                this.radioButtonStartup.Checked = false;

                // Enable dropdown for day choosing
                this.comboBoxDay.Enabled = true;
                this.timePicker.Enabled = false;
                this.comboBoxInterval.Enabled = false;
            }
        }

        private void buttonPrevious_Click(object sender, EventArgs e)
        {
            // Set previous wallpaper as current
            WallpaperManager.Instance.SetPreviousWallpaper();
            
        }

        private void buttonNext_Click(object sender, EventArgs e)
        {
            // Set next wallpaper as current
            WallpaperManager.Instance.SetNextWallpaper();
            // Restart timer
            Program.CurrentSession.ActiveCondition.ManualChangeCallback();
        }

        private void linkLabelWebsite_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            // Open project page with standard browser
            Process.Start("http://wpcontrol.sourceforge.net/");
        }

        private void checkBoxLoop_CheckedChanged(object sender, EventArgs e)
        {
            // A balloon tip for repeating info can't be shown if repeating is 
            // disabled.
            // Check if repeating is enabled
            if (checkBoxLoop.Checked)
            {
                // If yes enable possibility to enable balloon tip
                checkBoxRepeatingTip.Enabled = true;
            }
            else
            {
                // If not disable possibility and deselect it
                checkBoxRepeatingTip.Enabled = false;
                checkBoxRepeatingTip.Checked = false;
            }

            // Save setting
            Program.Configuration.LoopWallpapers = this.checkBoxLoop.Checked;
        }

        /// <summary>
        /// Updates the ControlPanel so that the form status matches the restored 
        /// settings from the config files.
        /// </summary>
        internal void RestoreValues()
        {
            this.LoadImageList();
            this.UpdateSettings();
            this.UpdateSchedule();
            this.UpdateImageButtons();
        }

        /// <summary>
        /// Loads the settings so that the ControlPanel is up-to-date.
        /// </summary>
        internal void UpdateSettings()
        {
            // Modify checkboxes according to loaded setting
            if (Program.Configuration.StartWithWindows)
            {
                Program.ControlPanel.checkBoxOnSysStart.Checked = true;
            }
            else
            {
                Program.ControlPanel.checkBoxOnSysStart.Checked = false;
            }

            if (Program.Configuration.StartWithControlPanel)
            {
                Program.ControlPanel.checkBoxControlPanel.Checked = true;
            }
            else
            {
                Program.ControlPanel.checkBoxControlPanel.Checked = false;
            }

            if (Program.Configuration.ChangeInfo)
            {
                Program.ControlPanel.checkBoxChangeTip.Checked = true;
            }
            else
            {
                Program.ControlPanel.checkBoxChangeTip.Checked = false;
            }

            if (Program.Configuration.RunningInfo)
            {
                Program.ControlPanel.checkBoxRunningTip.Checked = true;
            }
            else
            {
                Program.ControlPanel.checkBoxRunningTip.Checked = false;
            }

            if (Program.Configuration.LoopingInfo)
            {
                Program.ControlPanel.checkBoxRepeatingTip.Checked = true;
            }
            else
            {
                Program.ControlPanel.checkBoxRepeatingTip.Checked = false;
            }

            if (Program.Configuration.LoopWallpapers)
            {
                Program.ControlPanel.checkBoxLoop.Checked = true;
            }
            else
            {
                Program.ControlPanel.checkBoxLoop.Checked = false;
            }
        }

        /// <summary>
        /// Restores the schedule values.
        /// </summary>
        internal void UpdateSchedule()
        {
            // Modify form depending on the current status (inactive/active)
            this.DisplayStatus();

            // Display name of the next and the current wallpaper
            this.DisplayInfo();

            // Display remaining time
            if (Program.CurrentSession.ActiveCondition != null)
            {
                this.DisplayChangeTime();
            }

            // Display change order
            this.DisplayChangeOrder();

            // Check if session is currently active
            if (Program.CurrentSession.IsActive)
            {
                // Check if wallpaper should loop
                if (!Program.Configuration.LoopWallpapers)
                {
                    // Check if it is possible to set next wallpaper and modify buttons
                    if (WallpaperManager.Instance.NextWallpaperIndex >= ImageList.Instance.Images.Count)
                    {
                        this.buttonNext.Enabled = false;
                    }
                    else
                    {
                        this.buttonNext.Enabled = true;
                    }
                    // Check if it is possible to set previous wallpaper and modify buttons
                    if (WallpaperManager.Instance.PreviousWallpaperIndex < 0)
                    {
                        this.buttonPrevious.Enabled = false;
                    }
                    else
                    {
                        this.buttonPrevious.Enabled = true;
                    }
                }
                // Wallpapers are looping
                else
                {
                    // Next wallpaper is alway possible
                    this.buttonNext.Enabled = true;
                    // Check if it is possible to set previous wallpaper
                    if (WallpaperManager.Instance.PreviousWallpaperIndex < 0)
                    {
                        this.buttonPrevious.Enabled = false;
                    }
                    else
                    {
                        this.buttonPrevious.Enabled = true;
                    }
                }
            }
            // Session is inactive
            else
            {
                // Disable next/previous wallpaper
                this.buttonNext.Enabled = false;
                this.buttonPrevious.Enabled = false;
                
            }
        }

        /// <summary>
        /// Displays/updates the current checking status.
        /// </summary>
        private void DisplayStatus()
        {
            // Check if session is active
            if (Program.CurrentSession.IsActive)
            {
                // Display status
                this.labelStatus.Text = Program.Lang.GetString("Status_Active");
                // Modify button text in schedule
                this.buttonStartStop.Text = Program.Lang.GetString("Action_DeactivateText");
                // Modify menu entry text in tray menu
                Program.TrayApp.ContextSession.Text = Program.Lang.GetString("Action_DeactivateText");
                // Make progress bar in schedule visible
                if (
                    Program.CurrentSession.ActiveCondition.Id == CondTime.CondId ||
                    Program.CurrentSession.ActiveCondition.Id == CondTimeInterval.CondId ||
                    Program.CurrentSession.ActiveCondition.Id == CondDayInterval.CondId
                   )
                {
                    this.progressBarTime.Visible = true;
                }
            }
            // Session is inactive
            else
            {
                // Display status
                this.labelStatus.Text = Program.Lang.GetString("Status_Inactive");
                // Modify buttin text in schedule
                this.buttonStartStop.Text = Program.Lang.GetString("Action_ActivateText");
                // Modify menu entry text in tray menu
                Program.TrayApp.ContextSession.Text = Program.Lang.GetString("Action_ActivateText");
                // Hide progress bar
                this.progressBarTime.Visible = false;
            }
        }
        
        /// <summary>
        /// Displays/updates the name of the next wallpaper in the schedule.
        /// </summary>
        private void DisplayInfo()
        {
            // Check if session is currently active
            if (Program.CurrentSession.IsActive)
            {
                if (this.DisplayNextWallpaper)
                {
                    // Check if next wallpaper index is correct
                    if (
                        WallpaperManager.Instance.NextWallpaperIndex < ImageList.Instance.Images.Count &&
                        WallpaperManager.Instance.NextWallpaperIndex >= 0
                       )
                    {
                        // Get path of the next wallpaper
                        string nextWallpaperPath = ImageList.Instance.Images[WallpaperManager.Instance.NextWallpaperIndex].Path;
                        // Display file name of the next wallpaper
                        this.nextWallpaperValue = Path.GetFileName(nextWallpaperPath);
                        this.WallpaperValue.Text = this.nextWallpaperValue;
                    }
                    // Index is not correct
                    else
                    {
                        // Check if wallpapers shall be looped
                        if (Program.Configuration.LoopWallpapers)
                        {
                            // Get real index
                            int realIndex = 0;
                            switch (WallpaperManager.Instance.Order)
                            {
                                case WallpaperManager.ChangeOrder.Descending:
                                    realIndex = 0 + (WallpaperManager.Instance.CurrentWallpaperIndex - (ImageList.Instance.Images.Count - 1));
                                    break;
                                case WallpaperManager.ChangeOrder.Ascending:
                                    realIndex = (ImageList.Instance.Images.Count - 1) - WallpaperManager.Instance.CurrentWallpaperIndex;
                                    break;
                            }
                            // Display file name of next wallpaper with the real index
                            string nextWallpaperPath = ImageList.Instance.Images[realIndex].Path;
                            this.WallpaperValue.Text = Path.GetFileName(nextWallpaperPath);
                        }
                        // No loop
                        else
                        {
                            // Values not available 
                            this.WallpaperValue.Text = Program.Lang.GetString("Value_NotAvailable");
                            this.TimeValue.Text = Program.Lang.GetString("Value_NotAvailable");
                            this.currWallpaperValue.Text = Program.Lang.GetString("Value_NotAvailable");
                        }
                    }
                }

                if (this.DisplayCurrentWallpaper)
                {
                    // Check if current wallpaper index is correct
                    if (
                        WallpaperManager.Instance.CurrentWallpaperIndex < ImageList.Instance.Images.Count &&
                        WallpaperManager.Instance.CurrentWallpaperIndex >= 0
                       )
                    {
                        // Display file name of current wallpaper
                        string currentWallpaperPath = ImageList.Instance.Images[WallpaperManager.Instance.CurrentWallpaperIndex].Path;
                        this.currWallpaperValue.Text = Path.GetFileName(currentWallpaperPath);
                    }
                    else
                    {
                        // Wallpapers shall be looped
                        if (Program.Configuration.LoopWallpapers)
                        {
                            // Get real index
                            int realIndex = 0;
                            switch (WallpaperManager.Instance.Order)
                            {
                                case WallpaperManager.ChangeOrder.Descending:
                                    realIndex = 0 + (WallpaperManager.Instance.CurrentWallpaperIndex - (ImageList.Instance.Images.Count - 1));
                                    break;
                                case WallpaperManager.ChangeOrder.Ascending:
                                    realIndex = WallpaperManager.Instance.CurrentWallpaperIndex - (ImageList.Instance.Images.Count - 1);
                                    break;
                            }
                            // Display file name based on real index
                            string currentWallpaperPath = ImageList.Instance.Images[realIndex].Path;
                            this.currWallpaperValue.Text = Path.GetFileName(currentWallpaperPath);
                        }
                        // No looping of wallpapers
                        else
                        {
                            // Values not available
                            this.WallpaperValue.Text = Program.Lang.GetString("Value_NotAvailable");
                            this.TimeValue.Text = Program.Lang.GetString("Value_NotAvailable");
                            this.currWallpaperValue.Text = Program.Lang.GetString("Value_NotAvailable");
                        }
                    }
                }
            }
            // Session is inactive
            else
            {
                // Values not available
                this.WallpaperValue.Text = Program.Lang.GetString("Value_NotAvailable");
                this.TimeValue.Text = Program.Lang.GetString("Value_NotAvailable");
                this.currWallpaperValue.Text = Program.Lang.GetString("Value_NotAvailable");
            }
        }

        /// <summary>
        /// Displays/updates the time value in the schedule.
        /// </summary>
        private void DisplayChangeTime()
        {
            // Check if active condition is time
            if (Program.CurrentSession.ActiveCondition.Id == 1)
            {
                // Check if session is currently active
                if (Program.CurrentSession.IsActive)
                {
                    // Calculate time until next change
                    TimeSpan difference = Program.CurrentSession.ActiveCondition.RemainingTime;
                    int diffHours = difference.Hours;
                    int diffMinutes = difference.Minutes;
                    int diffSeconds = difference.Seconds;

                    // Display result
                    if (diffMinutes > 0)
                    {
                        if (diffHours > 0)
                        {
                            TimeValue.Text = diffHours + ":" + diffMinutes + ":" + diffSeconds;
                        }
                        else
                        {
                            TimeValue.Text = diffMinutes + ":" + diffSeconds;
                        }
                    }
                }
                // Session is inactive
                else
                {
                    // Value is not available
                    Program.ControlPanel.TimeValue.Text = Program.Lang.GetString("Value_NotAvailable");
                }
            }
            // If condition is time interval
            else if (Program.CurrentSession.ActiveCondition.Id == 2)
            {
                if (Program.CurrentSession.IsActive)
                {
                    this.TimeValue.Text = Program.CurrentSession.ActiveCondition.RemainingTime.Seconds.ToString() + Program.Lang.GetString("Value_Seconds");
                    /*this.progressBarTime.Maximum = completeInterval;
                    this.progressBarTime.Value = currentInterval;*/
                }
                else
                {
                    Program.ControlPanel.TimeValue.Text = Program.Lang.GetString("Value_NotAvailable");
                }
            }

        }

        /// <summary>
        /// Display the chhange order in schedule by checking/unchecking the radio
        /// buttons.
        /// </summary>
        internal void DisplayChangeOrder()
        {
            switch (WallpaperManager.Instance.Order)
            {
                case WallpaperManager.ChangeOrder.Descending:
                    this.radioDescending.Checked = true;
                    this.radioAscending.Checked = false;
                    this.radioRandom.Checked = false;
                    break;
                case WallpaperManager.ChangeOrder.Ascending:
                    this.radioDescending.Checked = false;
                    this.radioAscending.Checked = true;
                    this.radioRandom.Checked = false;
                    break;
                case WallpaperManager.ChangeOrder.Random:
                    this.radioDescending.Checked = false;
                    this.radioAscending.Checked = false;
                    this.radioRandom.Checked = true;
                    break;
            }
        }

        /// <summary>
        /// Allows or disallows changing of the condition by the user.
        /// </summary>
        /// <param name="allowed">True if changing should be allowed, false otherwise.</param>
        internal void AllowConditionChanging(bool allowed)
        {
            if (allowed)
            {
                // Enable radio buttons used to choose condition
                this.radioButtonTime.Enabled = true;
                this.radioButtonInterval.Enabled = true;
                this.radioButtonStartup.Enabled = true;
                this.radioButtonDay.Enabled = true;
                // Enable sub-controls of the currently active condition
                if (Program.CurrentSession.ActiveCondition.Id == CondTime.CondId)
                {
                    this.timePicker.Enabled = true;
                }
                else if (Program.CurrentSession.ActiveCondition.Id == CondTimeInterval.CondId)
                {
                    this.comboBoxInterval.Enabled = true;
                }
                else if (Program.CurrentSession.ActiveCondition.Id == CondDayInterval.CondId)
                {
                    this.comboBoxDay.Enabled = true;
                }
                this.radioDescending.Enabled = true;
                this.radioAscending.Enabled = true;
                this.radioRandom.Enabled = true;
            }
            else
            {
                // Disable all related controls
                this.radioButtonTime.Enabled = false;
                this.radioButtonInterval.Enabled = false;
                this.radioButtonStartup.Enabled = false;
                this.radioButtonDay.Enabled = false;
                this.comboBoxInterval.Enabled = false;
                this.comboBoxDay.Enabled = false;
                this.timePicker.Enabled = false;
                this.radioDescending.Enabled = false;
                this.radioAscending.Enabled = false;
                this.radioRandom.Enabled = false;
            }
        }

        /// <summary>
        /// Allows or disallows changing the settings by the user.
        /// </summary>
        /// <param name="allowed">True if changing should be allowed, false otherwise.</param>
        internal void AllowSettingsChanging(bool allowed)
        {
            if (allowed)
            {
                // Enable buttons
                this.checkBoxOnSysStart.Enabled = true;
                this.checkBoxControlPanel.Enabled = true;
                this.checkBoxLoop.Enabled = true;
                this.checkBoxChangeTip.Enabled = true;
                this.checkBoxRepeatingTip.Enabled = true;
                this.checkBoxRunningTip.Enabled = true;
            }
            else
            {
                // Disable buttons
                this.checkBoxOnSysStart.Enabled = false;
                this.checkBoxControlPanel.Enabled = false;
                this.checkBoxLoop.Enabled = false;
                this.checkBoxChangeTip.Enabled = false;
                this.checkBoxRepeatingTip.Enabled = false;
                this.checkBoxRunningTip.Enabled = false;
            }
        }

        /// <summary>
        /// Allows or disallows if the user can preview images, set them as wallpaper
        /// and change the style the order.
        /// </summary>
        /// <param name="allowed">True if this actions should be allowed.</param>
        internal void AllowImageActions(bool allowed)
        {
            if (allowed)
            {
                // Enable buttons
                this.buttonUp.Enabled = true;
                this.buttonDown.Enabled = true;
                this.buttonShowNow.Enabled = true;
                this.buttonPreview.Enabled = true;
                this.dropdownStyle.Enabled = true;
            }
            else
            {
                // Disable buttons
                this.buttonUp.Enabled = false;
                this.buttonDown.Enabled = false;
                this.buttonShowNow.Enabled = false;
                this.buttonPreview.Enabled = false;
                this.dropdownStyle.Enabled = false;
            }
        }

        /// <summary>
        /// Allows or disallows if the user can add and remove images from/to the list.
        /// </summary>
        /// <param name="allowed">True if adding and removing of images should be allowed.</param>
        internal void AllowImageListActions(bool allowed)
        {
            if (allowed)
            {
                // Enable buttons
                this.buttonAdd.Enabled = true;
                this.buttonDelete.Enabled = true;
                this.buttonDeleteAll.Enabled = true;
            }
            else
            {
                // Disable buttons
                this.buttonAdd.Enabled = false;
                this.buttonDelete.Enabled = false;
                this.buttonDeleteAll.Enabled = false;
            }
        }

        /// <summary>
        /// Allows or disallows if the user can add or remove image from/to the list.
        /// </summary>
        /// <param name="isAddingAllowed">True if adding images to the list should be allowed.</param>
        /// <param name="isRemovingAllowed">True if removing images from the list should be allowed.</param>
        internal void AllowImageListActions(bool isAddingAllowed, bool isRemovingAllowed)
        {
            // Enable adding new images
            if (isAddingAllowed)
            {
                this.buttonAdd.Enabled = true;
            }
            // Disable adding new images
            else
            {
                this.buttonAdd.Enabled = false;
            }

            // Enable removing images
            if (isRemovingAllowed)
            {
                this.buttonDelete.Enabled = true;
                this.buttonDeleteAll.Enabled = true;
            }
            // Disable removing images
            else
            {
                this.buttonDelete.Enabled = false;
                // Check if there is at least one image in the list
                if (ImageList.Instance.Images.Count > 0)
                {
                    this.buttonDeleteAll.Enabled = true;
                }
                else
                {
                    this.buttonDeleteAll.Enabled = false;
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        internal void UpdateImageButtons()
        {
            // Check if there is a session running
            if (Program.CurrentSession.IsActive)
            {
                // Disallow manipulating the image list
                this.AllowImageListActions(false);
                this.AllowImageActions(false);
            }
            else
            {
                // Check if the user has selected an image and modify controls
                if (this.listBoxImages.SelectedIndex == -1)
                {
                    this.AllowImageActions(false);
                    this.AllowImageListActions(true, false);
                }
                else
                {
                    this.AllowImageActions(true);
                    this.AllowImageListActions(true);
                }
            }
        }

        /// <summary>
        /// Restores the loaded images.
        /// </summary>
        internal void LoadImageList()
        {
            if (this.listBoxImages.Items.Count < ImageList.Instance.Images.Count)
            {
                // Used to indicate correct position in list
                int index = 0;
                foreach (string currentItem in this.listBoxImages.Items)
                {
                    this.listBoxImages.Items.Remove(currentItem);
                }
                // Go through every item in image list.
                foreach (Wallpaper i in ImageList.Instance.Images)
                {
                    // Add current item to listbox
                    this.listBoxImages.Items.Insert(index, i.Path);
                    // Next position
                    index++;
                }
            }
        }

        private void buttonStartStop_Click(object sender, EventArgs e)
        {
            // Modify start/stop button according to current session status
            if (!Program.CurrentSession.IsActive)
            {
                Program.CurrentSession.Start();
            }
            else
            {
                Program.CurrentSession.Stop();
            }
            // Keep ControlPanel up-to-date
            this.UpdateSchedule();
            this.UpdateImageButtons();
        }

        private void dropdownStyle_SelectedIndexChanged(object sender, EventArgs e)
        {
            // Save zoom style immediately if it is changed
            // Get index of selected image
            int selectedImage = this.ListBoxImages.SelectedIndex;
            // Get index of selected zoom style
            int selectedStyleIndex = this.DropDownStyle.SelectedIndex;
            // Make sure an image has been selected
            if (selectedImage != -1 && selectedStyleIndex != -1)
            {
                // Determine what style is selected
                Wallpaper.Style selectedStyle;
                // Streteched Wallpaper
                if (this.DropDownStyle.SelectedValue.ToString() == this.StyleNames[0])
                {
                    selectedStyle = Wallpaper.Style.Stretched;
                }
                // Tiled Wallpaper
                else if (this.DropDownStyle.SelectedValue.ToString() == this.StyleNames[1])
                {
                    selectedStyle = Wallpaper.Style.Tiled;
                }
                // Centered Wallpaper
                else if (this.DropDownStyle.SelectedValue.ToString() == this.StyleNames[2])
                {
                    selectedStyle = Wallpaper.Style.Centered;
                }
                else
                {
                    // default value
                    selectedStyle = 0;
                }
                // Save selected style into the style list
                ImageList.Instance.Images[selectedImage].ZoomStyle = selectedStyle;
            }
        }

        private void buttonDeleteAll_Click(object sender, EventArgs e)
        {
            // Remove all images
            ImageList.Instance.RemoveAllImages();
        }

        private void checkBoxOnSysStart_CheckedChanged(object sender, EventArgs e)
        {
            // Save setting
            Program.Configuration.StartWithWindows = this.checkBoxOnSysStart.Checked;
        }

        private void checkBoxControlPanel_CheckedChanged(object sender, EventArgs e)
        {
            Program.Configuration.StartWithControlPanel = this.checkBoxControlPanel.Checked;
        }

        private void checkBoxChangeTip_CheckedChanged(object sender, EventArgs e)
        {
            Program.Configuration.ChangeInfo = this.checkBoxChangeTip.Checked;
        }

        private void checkBoxRunningTip_CheckedChanged(object sender, EventArgs e)
        {
            Program.Configuration.RunningInfo = this.checkBoxRunningTip.Checked;
        }

        private void checkBoxRepeatingTip_CheckedChanged(object sender, EventArgs e)
        {
            Program.Configuration.LoopingInfo = this.checkBoxRepeatingTip.Checked;
        }

        private void comboBoxInterval_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (this.comboBoxInterval.SelectedIndex != -1 && this.comboBoxInterval.SelectedIndex <= CondTimeInterval.IntervalSeconds.GetLength(0))
            {
                Program.CurrentSession.ActiveCondition.ApplyValue();
            }
        }

        /// <summary>
        /// Finds out if this form is already opened.
        /// </summary>
        /// <returns>True if form is open, false otherwise.</returns>
        internal static bool IsOpen
        {
            get
            {
                foreach (Form openForm in Application.OpenForms)
                {
                    if (openForm is ControlPanel)
                    {
                        return true;
                    }
                }
                return false;
            }
        }

        private void comboBoxDay_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (this.comboBoxInterval.SelectedIndex != -1 && this.comboBoxInterval.SelectedIndex <= CondDayInterval.Days.GetLength(0))
            {
                Program.CurrentSession.ActiveCondition.ApplyValue();
            }
        }

        private void timePicker_ValueChanged(object sender, EventArgs e)
        {
            if (DateTime.Compare(DateTime.Now, this.timePicker.Value) < 0)
            {
                Program.CurrentSession.ActiveCondition.ApplyValue();
            }
            else
            {
                // TODO: Show message box - invalid value
            }
        }

        private void ControlPanel_Click(object sender, EventArgs e)
        {
            this.listBoxImages.SelectedIndex = -1;
        }

        private void tabWallpapers_Click(object sender, EventArgs e)
        {
            this.listBoxImages.SelectedIndex = -1;
        }

        private void listBoxImages_DragEnter(object sender, System.Windows.Forms.DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                e.Effect = DragDropEffects.Link;
            }
        }

        private void listBoxImages_DragOver(object sender, System.Windows.Forms.DragEventArgs e)
        {
            
        }

        private void listBoxImages_DragDrop(object sender, System.Windows.Forms.DragEventArgs e)
        {
            // Verify that a file is dropped
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                // Go through every selected image.
                foreach (string file in (string[])e.Data.GetData(DataFormats.FileDrop))
                {
                    Image image = new Image(file);
                    // Check if image is supported
                    if (image.IsSupported())
                    {
                        try
                        {
                            // Add image to list
                            ImageList.Instance.AddImage(new Wallpaper(file, Wallpaper.Style.Stretched));
                        }
                        catch (WallpaperPathException)
                        {
                            // TODO
                        }
                        catch (ImageFormatException)
                        {
                        }
                        catch (WallpaperFileException)
                        {
                        }
                    }
                }
            }
        }

        private void radioDescending_CheckedChanged(object sender, EventArgs e)
        {
            if (this.radioDescending.Enabled)
            {
                WallpaperManager.Instance.Order = WallpaperManager.ChangeOrder.Descending;
            }
        }

        private void radioAscending_CheckedChanged(object sender, EventArgs e)
        {
            if (this.radioAscending.Enabled)
            {
                WallpaperManager.Instance.Order = WallpaperManager.ChangeOrder.Ascending;
            }
        }

        private void radioRandom_CheckedChanged(object sender, EventArgs e)
        {
            if (this.radioRandom.Enabled)
            {
                WallpaperManager.Instance.Order = WallpaperManager.ChangeOrder.Random;
            }
        }
    }
}
